﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace YinLongTool.Net.Http
{
	public class CookieHelper
	{
		public struct pairItem
		{
			public string key;

			public string value;
		}

		private const char replacedChar = '_';

		private Dictionary<string, DateTime> calcTimeList;

		private string[] cookieFieldArr = new string[6]
		{
		"expires",
		"domain",
		"secure",
		"path",
		"httponly",
		"version"
		};

		private List<string> cookieFieldList = new List<string>();

		private CookieCollection curCookies = null;

		public static List<Cookie> GetAllCookies(CookieContainer cc)
		{
			List<Cookie> list = new List<Cookie>();
			Hashtable hashtable = (Hashtable)cc.GetType().InvokeMember("m_domainTable", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, cc, new object[0]);
			foreach (object value in hashtable.Values)
			{
				SortedList sortedList = (SortedList)value.GetType().InvokeMember("m_list", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, value, new object[0]);
				foreach (CookieCollection value2 in sortedList.Values)
				{
					foreach (Cookie item in value2)
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		public CookieHelper()
		{
			ServicePointManager.DefaultConnectionLimit = 200;
			curCookies = new CookieCollection();
			string[] array = cookieFieldArr;
			foreach (string item in array)
			{
				cookieFieldList.Add(item);
			}
			calcTimeList = new Dictionary<string, DateTime>();
		}

		private string _recoverExpireField(Match foundPprocessedExpire)
		{
			string text = "";
			return foundPprocessedExpire.Value.Replace('_', ',');
		}

		private string _processExpireField(Match foundExpire)
		{
			string text = "";
			return foundExpire.Value.ToString().Replace(',', '_');
		}

		public double mathRandom()
		{
			Random random = new Random();
			return random.NextDouble();
		}

		public void elapsedTimeSpanInit(string keyName)
		{
			calcTimeList.Add(keyName, DateTime.Now);
		}

		public double getElapsedTimeSpan(string keyName)
		{
			double result = 0.0;
			if (calcTimeList.ContainsKey(keyName))
			{
				DateTime d = calcTimeList[keyName];
				DateTime now = DateTime.Now;
				result = (now - d).TotalMilliseconds;
			}
			return result;
		}

		public double getCurTimeInMillisec()
		{
			DateTime d = new DateTime(1970, 1, 1);
			return (DateTime.Now - d).TotalMilliseconds;
		}

		public DateTime milliSecToDateTime(double milliSecSinceEpoch)
		{
			return new DateTime(1970, 1, 1, 0, 0, 0).AddMilliseconds(milliSecSinceEpoch);
		}

		public string encodeExclamationMark(string inputStr)
		{
			return inputStr.Replace("!", "%21");
		}

		public string decodeExclamationMark(string inputStr)
		{
			return inputStr.Replace("%21", "!");
		}

		public bool extractSingleStr(string pattern, string extractFrom, out string extractedStr)
		{
			bool flag = false;
			Regex regex = new Regex(pattern);
			Match match = regex.Match(extractFrom);
			if (match.Success)
			{
				flag = true;
				extractedStr = match.Groups[1].ToString();
			}
			else
			{
				flag = false;
				extractedStr = "";
			}
			return flag;
		}

		public string quoteParas(Dictionary<string, string> paras)
		{
			string text = "";
			bool flag = true;
			string value = "";
			foreach (string key in paras.Keys)
			{
				if (!paras.TryGetValue(key, out value))
				{
					break;
				}
				if (flag)
				{
					flag = false;
					text = text + key + "=" + HttpUtility.UrlPathEncode(value);
				}
				else
				{
					string text2 = text;
					text = text2 + "&" + key + "=" + HttpUtility.UrlPathEncode(value);
				}
			}
			return text;
		}

		public string[] getSubStrArr(string[] origStrArr, int startIdx, int len)
		{
			string[] array = new string[0];
			if (origStrArr != null && origStrArr.Length > 0 && len > 0)
			{
				List<string> list = new List<string>();
				int num = startIdx + len;
				if (num > origStrArr.Length)
				{
					num = origStrArr.Length;
				}
				for (int i = startIdx; i < num; i++)
				{
					list.Add(origStrArr[i]);
				}
				array = new string[len];
				list.CopyTo(array);
			}
			return array;
		}

		public string extractHost(string url)
		{
			string result = "";
			if (url != "" && url.Contains("/"))
			{
				string[] array = url.Split('/');
				result = array[2];
			}
			return result;
		}

		public string extractDomain(string url)
		{
			string text = "";
			string result = "";
			text = extractHost(url);
			if (text.Contains("."))
			{
				result = text.Substring(text.IndexOf('.'));
			}
			return result;
		}

		public bool addFieldToCookie(ref Cookie ck, pairItem pairInfo)
		{
			bool result = false;
			if (pairInfo.key != "")
			{
				switch (pairInfo.key.ToLower())
				{
					case "expires":
						{
							if (DateTime.TryParse(pairInfo.value, out DateTime result3))
							{
								ck.Expires = result3;
								if (DateTime.Now.Ticks > ck.Expires.Ticks)
								{
									ck.Expired = true;
								}
								result = true;
							}
							break;
						}
					case "domain":
						ck.Domain = pairInfo.value;
						result = true;
						break;
					case "secure":
						ck.Secure = true;
						result = true;
						break;
					case "path":
						ck.Path = pairInfo.value;
						result = true;
						break;
					case "httponly":
						ck.HttpOnly = true;
						result = true;
						break;
					case "version":
						{
							if (int.TryParse(pairInfo.value, out int result2))
							{
								ck.Version = result2;
								result = true;
							}
							break;
						}
				}
			}
			return result;
		}

		public bool isValidCookieField(string cookieKey)
		{
			return cookieFieldList.Contains(cookieKey.ToLower());
		}

		public bool isValidCookieName(string ckName)
		{
			bool result = true;
			if (ckName == null)
			{
				result = false;
			}
			else
			{
				string pattern = "[^A-Za-z0-9_.]";
				Regex regex = new Regex(pattern);
				Match match = regex.Match(ckName);
				if (match.Success)
				{
					result = false;
				}
			}
			return result;
		}

		public bool parseCookieNameValue(string ckNameValueExpr, out pairItem pair)
		{
			bool flag = false;
			if (ckNameValueExpr == "")
			{
				pair.key = "";
				pair.value = "";
				return false;
			}
			ckNameValueExpr = ckNameValueExpr.Trim();
			int num = ckNameValueExpr.IndexOf('=');
			if (num > 0)
			{
				pair.key = ckNameValueExpr.Substring(0, num);
				pair.key = pair.key.Trim();
				if (isValidCookieName(pair.key))
				{
					pair.value = ckNameValueExpr.Substring(num + 1);
					pair.value = pair.value.Trim();
					return true;
				}
				pair.key = "";
				pair.value = "";
				return false;
			}
			pair.key = "";
			pair.value = "";
			return false;
		}

		public bool parseCookieField(string ckFieldExpr, out pairItem pair)
		{
			bool flag = false;
			if (ckFieldExpr == "")
			{
				pair.key = "";
				pair.value = "";
				return false;
			}
			ckFieldExpr = ckFieldExpr.Trim();
			if (ckFieldExpr.ToLower() == "httponly")
			{
				pair.key = "httponly";
				pair.value = "true";
				return true;
			}
			if (ckFieldExpr.ToLower() == "secure")
			{
				pair.key = "secure";
				pair.value = "true";
				return true;
			}
			int num = ckFieldExpr.IndexOf('=');
			if (num > 0)
			{
				pair.key = ckFieldExpr.Substring(0, num);
				pair.key = pair.key.Trim();
				if (isValidCookieField(pair.key))
				{
					pair.value = ckFieldExpr.Substring(num + 1);
					pair.value = pair.value.Trim();
					return true;
				}
				pair.key = "";
				pair.value = "";
				return false;
			}
			pair.key = "";
			pair.value = "";
			return false;
		}

		public bool parseSingleCookie(string cookieStr, ref Cookie ck)
		{
			if (string.IsNullOrEmpty(cookieStr))
			{
				return false;
			}
			bool result = true;
			string[] array = cookieStr.Split(new char[1]
			{
			';'
			}, StringSplitOptions.RemoveEmptyEntries);
			pairItem pair = default(pairItem);
			if (parseCookieNameValue(array[0], out pair))
			{
				ck.Name = pair.key;
				ck.Value = pair.value;
				string[] subStrArr = getSubStrArr(array, 1, array.Length - 1);
				string[] array2 = subStrArr;
				foreach (string ckFieldExpr in array2)
				{
					if (parseCookieField(ckFieldExpr, out pair))
					{
						addFieldToCookie(ref ck, pair);
						continue;
					}
					result = false;
					break;
				}
			}
			else
			{
				result = false;
			}
			return result;
		}

		private bool needAddThisCookie(Cookie ck, string curDomain)
		{
			bool flag = false;
			if (ck == null || ck.Name == "")
			{
				return false;
			}
			return true;
		}

		public List<Cookie> parseSetCookie(string setCookieStr, string curDomain)
		{
			List<Cookie> list = new List<Cookie>();
			string text = Regex.Replace(setCookieStr, "xpires=\\w{3},\\s\\d{2}-\\w{3}-\\d{4}", _processExpireField);
			string[] array = text.Split(',');
			string[] array2 = array;
			foreach (string text2 in array2)
			{
				if (!string.IsNullOrEmpty(text2))
				{
					Cookie ck = new Cookie();
					string cookieStr = Regex.Replace(text2, "xpires=\\w{3}" + '_' + "\\s\\d{2}-\\w{3}-\\d{4}", _recoverExpireField);
					if (parseSingleCookie(cookieStr, ref ck) && needAddThisCookie(ck, curDomain))
					{
						list.Add(ck);
					}
				}
			}
			return list;
		}

		public List<Cookie> parseSetCookie(string setCookieStr)
		{
			return parseSetCookie(setCookieStr, "");
		}

		public bool parseJsNewDate(string newDateStr, out DateTime parsedDatetime)
		{
			bool result = false;
			parsedDatetime = default(DateTime);
			if (newDateStr != "" && newDateStr.Trim() != "")
			{
				string extractedStr = "";
				if (extractSingleStr(".*new\\sDate\\((.+?)\\).*", newDateStr, out extractedStr))
				{
					double result2 = 0.0;
					if (double.TryParse(extractedStr, out result2))
					{
						parsedDatetime = milliSecToDateTime(result2);
						result = true;
					}
					else if (DateTime.TryParse(extractedStr, out parsedDatetime))
					{
						result = true;
					}
				}
			}
			return result;
		}

		public bool parseJsSetCookie(string singleSetCookieStr, out Cookie parsedCk)
		{
			bool result = false;
			parsedCk = new Cookie();
			string text = "";
			string text2 = "";
			string text3 = "";
			string text4 = "";
			string text5 = "";
			string text6 = "";
			string pattern = "\\$Cookie\\.setCookie\\('(\\w+)',\\s*'(.*?)',\\s*'([\\w\\.]+)',\\s*'(.+?)',\\s*(.+?),\\s*(\\d?)\\);";
			Regex regex = new Regex(pattern);
			Match match = regex.Match(singleSetCookieStr);
			if (match.Success)
			{
				text = match.Groups[1].ToString();
				text2 = match.Groups[2].ToString();
				text3 = match.Groups[3].ToString();
				text4 = match.Groups[4].ToString();
				text5 = match.Groups[5].ToString();
				text6 = match.Groups[6].ToString();
				if (isValidCookieName(text) && text3 != "")
				{
					result = true;
					parsedCk.Name = text;
					parsedCk.Value = text2;
					parsedCk.Domain = text3;
					parsedCk.Path = text4;
					if (!(text5.Trim() == "null") && parseJsNewDate(text5, out DateTime parsedDatetime))
					{
						parsedCk.Expires = parsedDatetime;
					}
					if (text6 == "1")
					{
						parsedCk.Secure = true;
					}
					else
					{
						parsedCk.Secure = false;
					}
				}
			}
			return result;
		}

		public bool isCookieExpired(Cookie ck)
		{
			bool result = false;
			if (ck != null && ck.Name != "")
			{
				if (ck.Expired)
				{
					result = true;
				}
				else
				{
					DateTime expires = new Cookie().Expires;
					DateTime expires2 = ck.Expires;
					if (!expires2.Equals(expires) && DateTime.Now.Ticks > expires2.Ticks)
					{
						result = true;
					}
				}
			}
			else
			{
				result = true;
			}
			return result;
		}

		public void addCookieToCookies(Cookie toAdd, ref CookieCollection cookies, bool overwriteDomain)
		{
			bool flag = false;
			if (cookies.Count > 0)
			{
				foreach (Cookie cooky in cookies)
				{
					if (cooky.Name == toAdd.Name && (cooky.Domain == toAdd.Domain || (cooky.Domain != toAdd.Domain && overwriteDomain)))
					{
						cooky.Value = toAdd.Value;
						cooky.Domain = toAdd.Domain;
						cooky.Expires = toAdd.Expires;
						cooky.Version = toAdd.Version;
						cooky.Path = toAdd.Path;
						flag = true;
						break;
					}
				}
			}
			if (!flag && toAdd.Domain != "")
			{
				cookies.Add(toAdd);
			}
		}

		public void addCookieToCookies(Cookie toAdd, ref CookieCollection cookies)
		{
			addCookieToCookies(toAdd, ref cookies, false);
		}

		public bool isContainCookie(object ckToCheck, object cookies)
		{
			bool result = false;
			if (ckToCheck != null && cookies != null)
			{
				string a = "";
				Type type = ckToCheck.GetType();
				if (type.Name.ToLower() == "string")
				{
					a = (string)ckToCheck;
				}
				else if (type.Name == "Cookie")
				{
					a = ((Cookie)ckToCheck).Name;
				}
				if (a != "")
				{
					type = cookies.GetType();
					if (type.Name == "Cookie")
					{
						if (a == ((Cookie)cookies).Name)
						{
							result = true;
						}
					}
					else if (type.Name == "CookieCollection")
					{
						foreach (Cookie item in (CookieCollection)cookies)
						{
							if (a == item.Name)
							{
								result = true;
								break;
							}
						}
					}
					else if (type.Name.ToLower() == "string")
					{
						if (a == (string)cookies)
						{
							result = true;
						}
					}
					else if (type.Name.ToLower() == "string[]")
					{
						string[] array = (string[])cookies;
						foreach (string b in array)
						{
							if (a == b)
							{
								result = true;
								break;
							}
						}
					}
				}
			}
			return result;
		}

		public void updateLocalCookies(CookieCollection cookiesToUpdate, ref CookieCollection localCookies, object omitUpdateCookies)
		{
			if (cookiesToUpdate.Count > 0)
			{
				if (localCookies == null)
				{
					localCookies = cookiesToUpdate;
				}
				else
				{
					foreach (Cookie item in cookiesToUpdate)
					{
						if (!isContainCookie(item, omitUpdateCookies))
						{
							addCookieToCookies(item, ref localCookies);
						}
					}
				}
			}
		}

		public void updateLocalCookies(CookieCollection cookiesToUpdate, ref CookieCollection localCookies)
		{
			updateLocalCookies(cookiesToUpdate, ref localCookies, null);
		}

		public bool getCookieVal(string ckName, ref CookieCollection cookies, out string ckVal)
		{
			ckVal = "";
			bool result = false;
			foreach (Cookie cooky in cookies)
			{
				if (cooky.Name == ckName)
				{
					result = true;
					ckVal = cooky.Value;
					break;
				}
			}
			return result;
		}

		public bool serializeObjToStr(object obj, out string serializedStr)
		{
			bool flag = false;
			serializedStr = "";
			try
			{
				MemoryStream memoryStream = new MemoryStream();
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				binaryFormatter.Serialize(memoryStream, obj);
				serializedStr = Convert.ToBase64String(memoryStream.ToArray());
				return true;
			}
			catch
			{
				return false;
			}
		}

		public bool deserializeStrToObj(string serializedStr, out object deserializedObj)
		{
			bool flag = false;
			deserializedObj = null;
			try
			{
				byte[] buffer = Convert.FromBase64String(serializedStr);
				MemoryStream serializationStream = new MemoryStream(buffer);
				BinaryFormatter binaryFormatter = new BinaryFormatter();
				deserializedObj = binaryFormatter.Deserialize(serializationStream);
				return true;
			}
			catch
			{
				return false;
			}
		}

		public void clearCurCookies()
		{
			if (curCookies != null)
			{
				curCookies = null;
				curCookies = new CookieCollection();
			}
		}

		public CookieCollection getCurCookies()
		{
			return curCookies;
		}

		public void setCurCookies(CookieCollection cookies)
		{
			curCookies = cookies;
		}

		public HttpWebResponse getUrlResponse(string url, Dictionary<string, string> headerDict, Dictionary<string, string> postDict, int timeout, string postDataStr)
		{
			HttpWebResponse httpWebResponse = null;
			HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
			httpWebRequest.AllowAutoRedirect = true;
			httpWebRequest.Accept = "*/*";
			httpWebRequest.KeepAlive = true;
			httpWebRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E";
			httpWebRequest.Headers["Accept-Encoding"] = "gzip, deflate";
			httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip;
			httpWebRequest.Proxy = null;
			if (timeout > 0)
			{
				httpWebRequest.Timeout = timeout;
			}
			if (curCookies != null)
			{
				httpWebRequest.CookieContainer = new CookieContainer();
				httpWebRequest.CookieContainer.PerDomainCapacity = 40;
				httpWebRequest.CookieContainer.Add(curCookies);
			}
			if (headerDict != null)
			{
				foreach (string key in headerDict.Keys)
				{
					string value = "";
					if (!headerDict.TryGetValue(key, out value))
					{
						break;
					}
					if (key.ToLower() == "referer")
					{
						httpWebRequest.Referer = value;
					}
					else if (key.ToLower() == "allowautoredirect")
					{
						bool result = false;
						if (bool.TryParse(value, out result))
						{
							httpWebRequest.AllowAutoRedirect = result;
						}
					}
					else if (key.ToLower() == "accept")
					{
						httpWebRequest.Accept = value;
					}
					else if (key.ToLower() == "keepalive")
					{
						bool result2 = false;
						if (bool.TryParse(value, out result2))
						{
							httpWebRequest.KeepAlive = result2;
						}
					}
					else if (key.ToLower() == "accept-language")
					{
						httpWebRequest.Headers["Accept-Language"] = value;
					}
					else if (key.ToLower() == "useragent")
					{
						httpWebRequest.UserAgent = value;
					}
					else
					{
						httpWebRequest.Headers[key] = value;
					}
				}
			}
			if (postDict != null || postDataStr != "")
			{
				httpWebRequest.Method = "POST";
				httpWebRequest.ContentType = "application/x-www-form-urlencoded";
				if (postDict != null)
				{
					postDataStr = quoteParas(postDict);
				}
				byte[] bytes =System.Text.Encoding.UTF8.GetBytes(postDataStr);
				httpWebRequest.ContentLength = bytes.Length;
				Stream requestStream = httpWebRequest.GetRequestStream();
				requestStream.Write(bytes, 0, bytes.Length);
				requestStream.Close();
			}
			else
			{
				httpWebRequest.Method = "GET";
			}
			httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
			updateLocalCookies(httpWebResponse.Cookies, ref curCookies);
			return httpWebResponse;
		}

		public HttpWebResponse getUrlResponse(string url, Dictionary<string, string> headerDict, Dictionary<string, string> postDict)
		{
			return getUrlResponse(url, headerDict, postDict, 0, "");
		}

		public HttpWebResponse getUrlResponse(string url)
		{
			return getUrlResponse(url, null, null, 0, "");
		}

		public string getUrlRespHtml(string url, Dictionary<string, string> headerDict, string charset, Dictionary<string, string> postDict, int timeout, string postDataStr)
		{
			string text = "";
			HttpWebResponse urlResponse = getUrlResponse(url, headerDict, postDict, timeout, postDataStr);
			StreamReader streamReader;
			if (charset != null && charset != "")
			{
				System.Text.Encoding encoding = System.Text.Encoding.GetEncoding(charset);
				streamReader = new StreamReader(urlResponse.GetResponseStream(), encoding);
			}
			else
			{
				streamReader = new StreamReader(urlResponse.GetResponseStream());
			}
			return streamReader.ReadToEnd();
		}

		public string getUrlRespHtml(string url, Dictionary<string, string> headerDict, string charset, Dictionary<string, string> postDict, string postDataStr)
		{
			return getUrlRespHtml(url, headerDict, charset, postDict, 0, postDataStr);
		}

		public string getUrlRespHtml(string url, Dictionary<string, string> headerDict, Dictionary<string, string> postDict)
		{
			return getUrlRespHtml(url, headerDict, "", postDict, "");
		}

		public string getUrlRespHtml(string url, Dictionary<string, string> headerDict)
		{
			return getUrlRespHtml(url, headerDict, null);
		}

		public string getUrlRespHtml(string url, string charset, int timeout)
		{
			return getUrlRespHtml(url, null, charset, null, timeout, "");
		}

		public string getUrlRespHtml(string url, string charset)
		{
			return getUrlRespHtml(url, charset, 0);
		}

		public string getUrlRespHtml(string url)
		{
			return getUrlRespHtml(url, "");
		}

		public int getUrlRespStreamBytes(ref byte[] respBytesBuf, string url, Dictionary<string, string> headerDict, Dictionary<string, string> postDict, int timeout)
		{
			int num = 0;
			int num2 = 0;
			try
			{
				HttpWebResponse urlResponse = getUrlResponse(url, headerDict, postDict);
				int num3 = (int)urlResponse.ContentLength;
				Stream responseStream = urlResponse.GetResponseStream();
				int num4;
				do
				{
					num4 = responseStream.Read(respBytesBuf, num, num3);
					if (num4 > 0)
					{
						num += num4;
						num3 -= num4;
						num2 += num4;
					}
				}
				while (num4 > 0);
			}
			catch
			{
				num2 = -1;
			}
			return num2;
		}

		public bool saveBytesToFile(string fileToSave, ref byte[] bytes, int dataLen, out string errStr)
		{
			bool result = false;
			errStr = "未知错误！";
			try
			{
				int offset = 0;
				FileStream fileStream = File.Create(fileToSave, dataLen);
				fileStream.Write(bytes, offset, dataLen);
				fileStream.Close();
				result = true;
			}
			catch (Exception ex)
			{
				errStr = ex.Message;
			}
			return result;
		}
	}
}
